package com.kymatrix.mpo.plus.bpm.server.convert.definition;

import cn.hutool.core.date.LocalDateTimeUtil;
import cn.hutool.core.map.MapUtil;
import com.kymatrix.mpo.plus.bpm.server.flowable.util.BpmnModelUtils;
import com.kymatrix.mpo.plus.bpm.server.model.entity.definition.BpmCategoryEntity;
import com.kymatrix.mpo.plus.bpm.server.model.entity.definition.BpmFormEntity;
import com.kymatrix.mpo.plus.bpm.server.model.entity.definition.BpmProcessDefinitionInfoEntity;
import com.kymatrix.mpo.plus.bpm.server.model.form.process.QueryBpmProcessDefinitionResp;
import com.kymatrix.mpo.plus.common.business.common.PageResp;
import com.kymatrix.mpo.plus.common.util.BeanUtils;
import com.kymatrix.mpo.plus.common.util.CollectionUtils;
import java.util.List;
import java.util.Map;
import org.flowable.bpmn.model.BpmnModel;
import org.flowable.bpmn.model.UserTask;
import org.flowable.common.engine.impl.db.SuspensionState;
import org.flowable.engine.repository.Deployment;
import org.flowable.engine.repository.ProcessDefinition;
import org.mapstruct.Mapper;

/**
 * Bpm 流程定义的 Convert
 *
 */
@Mapper
public class BpmProcessDefinitionConvert {


    public static PageResp<QueryBpmProcessDefinitionResp> buildProcessDefinitionPage(PageResp<ProcessDefinition> page,
                                                                               Map<String, Deployment> deploymentMap,
                                                                               Map<String, BpmProcessDefinitionInfoEntity> processDefinitionInfoMap,
                                                                               Map<String, BpmFormEntity> formMap,
                                                                               Map<String, BpmCategoryEntity> categoryMap) {
        List<QueryBpmProcessDefinitionResp> list = buildProcessDefinitionList(page.getList(), deploymentMap, processDefinitionInfoMap, formMap, categoryMap);
        return new PageResp<>(list, page.getTotal());
    }

    public static List<QueryBpmProcessDefinitionResp> buildProcessDefinitionList(List<ProcessDefinition> list,
                                                                           Map<String, Deployment> deploymentMap,
                                                                           Map<String, BpmProcessDefinitionInfoEntity> processDefinitionInfoMap,
                                                                           Map<String, BpmFormEntity> formMap,
                                                                           Map<String, BpmCategoryEntity> categoryMap) {
        return CollectionUtils.convertList(list, definition -> {
            Deployment deployment = MapUtil.get(deploymentMap, definition.getDeploymentId(), Deployment.class);
            BpmProcessDefinitionInfoEntity processDefinitionInfo = MapUtil.get(processDefinitionInfoMap, definition.getId(), BpmProcessDefinitionInfoEntity.class);
            BpmFormEntity form = null;
            if (processDefinitionInfo != null) {
                form = MapUtil.get(formMap, processDefinitionInfo.getFormId(), BpmFormEntity.class);
            }
            BpmCategoryEntity category = MapUtil.get(categoryMap, definition.getCategory(), BpmCategoryEntity.class);
            return buildProcessDefinition(definition, deployment, processDefinitionInfo, form, category, null, null);
        });
    }

    public static QueryBpmProcessDefinitionResp buildProcessDefinition(ProcessDefinition definition,
                                                                 Deployment deployment,
                                                                 BpmProcessDefinitionInfoEntity processDefinitionInfo,
                                                                 BpmFormEntity form,
                                                                 BpmCategoryEntity category,
                                                                 BpmnModel bpmnModel,
                                                                 List<UserTask> startUserSelectUserTaskList) {
        QueryBpmProcessDefinitionResp respVO = BeanUtils.toBean(definition, QueryBpmProcessDefinitionResp.class);
        respVO.setSuspensionState(definition.isSuspended() ? SuspensionState.SUSPENDED.getStateCode() : SuspensionState.ACTIVE.getStateCode());
        // Deployment
        if (deployment != null) {
            respVO.setDeploymentTime(LocalDateTimeUtil.of(deployment.getDeploymentTime()));
        }
        // BpmProcessDefinitionInfoDO
        if (processDefinitionInfo != null) {
            copyTo(processDefinitionInfo, respVO);
            // Form
            if (form != null) {
                respVO.setFormName(form.getName());
            }
        }
        // Category
        if (category != null) {
            respVO.setCategoryName(category.getName());
        }
        // BpmnModel
        if (bpmnModel != null) {
            respVO.setBpmnXml(BpmnModelUtils.getBpmnXml(bpmnModel));
            respVO.setStartUserSelectTasks(BeanUtils.toBean(startUserSelectUserTaskList, QueryBpmProcessDefinitionResp.UserTask.class));
        }
        return respVO;
    }

    public static void copyTo(BpmProcessDefinitionInfoEntity from, QueryBpmProcessDefinitionResp to) {
        to.setIcon(from.getIcon());
        to.setDescription(from.getDescription());
        to.setFormType(from.getFormType());
        to.setFormId(from.getFormId());
        to.setFormConf(from.getFormConf());
        to.setFormFields(from.getFormFields());
        to.setFormCustomCreatePath(from.getFormCustomCreatePath());
        to.setFormCustomViewPath(from.getFormCustomViewPath());
    }

}
